--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LXST/Platforms/windows/soundcard.py e92d9c99e3ff274d4b48f2bd094de05c4bca4e5d (e92d9c99) Text, 33.93 KB
T8b949e# Adapted from Bastian Bechtold's soundcard library, originally released
T8b949e# under the BSD 3-Clause License
T8b949e#
T8b949e# https://github.com/bastibe/SoundCard
T8b949e#
T8b949e# Copyright (c) 2016 Bastian Bechtold
T8b949e# All rights reserved.
T8b949e#
T8b949e# Redistribution and use in source and binary forms, with or without
T8b949e# modification, are permitted provided that the following conditions are
T8b949e# met:
T8b949e#
T8b949e# 1. Redistributions of source code must retain the above copyright
T8b949e# notice, this list of conditions and the following disclaimer.
T8b949e#
T8b949e# 2. Redistributions in binary form must reproduce the above copyright
T8b949e# notice, this list of conditions and the following disclaimer in the
T8b949e# documentation and/or other materials provided with the
T8b949e# distribution.
T8b949e#
T8b949e# 3. Neither the name of the copyright holder nor the names of its
T8b949e# contributors may be used to endorse or promote products derived
T8b949e# from this software without specific prior written permission.
T8b949e#
T8b949e# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
T8b949e# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
T8b949e# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
T8b949e# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
T8b949e# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
T8b949e# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
T8b949e# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
T8b949e# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
T8b949e# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
T8b949e# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
T8b949e# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
T8b949e#
T8b949e# Modifications and improvements Copyright 2025 Mark Qvist, and released
T8b949e# under the same BSD 3-Clause License.
Tff7b72import T7ee787os
Tff7b72import T7ee787cffi
Tff7b72import T7ee787re
Tff7b72import T7ee787time
Tff7b72import T7ee787struct
Tff7b72import T7ee787collections
Tff7b72import T7ee787platform
Tff7b72import T7ee787warnings
Tff7b72import T7ee787threading
Tff7b72import T7ee787numpy
Tff7b72import T7ee787RNS
Te6edf3_ffi Tff7b72= Te6edf3cffiTff7b72.Td2a8ffFFITb4b4b4(Tb4b4b4)
Te6edf3_package_dirTb4b4b4, Te6edf3_ Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitTb4b4b4(Tff7b72__file__Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3_package_dirTb4b4b4, Ta5d6ff'Ta5d6ffmediafoundation.hTa5d6ff'Tb4b4b4)Tb4b4b4, Ta5d6ff'Ta5d6ffrtTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3_ffiTff7b72.Td2a8ffcdefTb4b4b4(Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e# Attempt to load by generic name first; fall back to the explicit DLL name if that fails.
T8b949e# On some Windows 11 systems with Python 3.11.x, omitting the ".dll" extension may not work.
Tff7b72tryTb4b4b4: Te6edf3_ole32 Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffdlopenTb4b4b4(Ta5d6ff'Ta5d6ffole32Ta5d6ff'Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4: Te6edf3_ole32 Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffdlopenTb4b4b4(Ta5d6ff'Ta5d6ffole32.dllTa5d6ff'Tb4b4b4)
Tff7b72def Td2a8fftidTb4b4b4(Tb4b4b4)Tb4b4b4: Tff7b72return Te6edf3threadingTff7b72.Td2a8ffget_native_idTb4b4b4(Tb4b4b4)
Te6edf3com_thread_ids Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72class T56d364_COMLibraryTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_lock Tff7b72= Te6edf3threadingTff7b72.Td2a8ffLockTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffinit_comTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3tidTb4b4b4(Tb4b4b4) Tff7b72in Te6edf3com_thread_idsTb4b4b4:
T8b949e# print(f"ATTEMPT TO REINIT COM FOR {tid()}")
Tff7b72return
Tff7b72elseTb4b4b4:
Te6edf3com_thread_idsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3tidTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3COINIT_MULTITHREADED Tff7b72= T79c0ff0x0
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffCOM INIT FROM SOUNDCARD Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3platformTff7b72.Td2a8ffwin32_verTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff'Ta5d6ff8Ta5d6ff'Tb4b4b4: Tff7b72raise Tf85149OSErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnsupported Windows versionTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4: Te6edf3hr Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffCoInitializeExTb4b4b4(Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4, Te6edf3COINIT_MULTITHREADEDTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcom_loaded Tff7b72= Tff7b72True
Tff7b72except Tf85149RuntimeError Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffGOT ERROR IN COM INIT: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
T8b949e# Error 0x80010106
Te6edf3RPC_E_CHANGED_MODE Tff7b72= T79c0ff0x80010106
Tff7b72if Te6edf3hr Tff7b72+ T79c0ff2 Tff7b72*Tff7b72* T79c0ff32 Tff7b72== Te6edf3RPC_E_CHANGED_MODETb4b4b4:
T8b949e# COM was already initialized before (e.g. by the
T8b949e# debugger), therefore trying to initialize it again
T8b949e# fails we can safely ignore this error, but we have
T8b949e# to make sure that we don't try to unload it
T8b949e# afterwards therefore we set this flag to False:
Tff7b72selfTff7b72.Td2a8ffcom_loaded Tff7b72= Tff7b72False
Tff7b72elseTb4b4b4: Tff7b72raise Te6edf3e
Tff7b72def Td2a8ffrelease_comTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3tidTb4b4b4(Tb4b4b4) Tff7b72in Te6edf3com_thread_idsTb4b4b4:
Te6edf3com_thread_idsTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3tidTb4b4b4(Tb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffCOM DE-INIT FROM SOUNDCARD Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3_ole32 Tff7b72!= Tff7b72NoneTb4b4b4: Te6edf3_ole32Tff7b72.Td2a8ffCoUninitializeTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4: Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffOLE32 WAS NONE! Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4: Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffNO TID FOR COM DE-INIT FROM SOUNDCARD Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Tff7b72__del__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffcom_loadedTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrelease_comTb4b4b4(Tb4b4b4)
Tf0883e@staticmethod
Tff7b72def Td2a8ffcheck_errorTb4b4b4(Te6edf3hresultTb4b4b4)Tb4b4b4:
T8b949e# see shared/winerror.h:
Te6edf3S_OK Tff7b72= T79c0ff0
Te6edf3E_NOINTERFACE Tff7b72= T79c0ff0x80004002
Te6edf3E_POINTER Tff7b72= T79c0ff0x80004003
Te6edf3E_OUTOFMEMORY Tff7b72= T79c0ff0x8007000e
Te6edf3E_INVALIDARG Tff7b72= T79c0ff0x80070057
Te6edf3CO_E_NOTINITIALIZED Tff7b72= T79c0ff0x800401f0
Te6edf3AUDCLNT_E_UNSUPPORTED_FORMAT Tff7b72= T79c0ff0x88890008
Tff7b72if Te6edf3hresult Tff7b72== Te6edf3S_OKTb4b4b4: Tff7b72return
Tff7b72elif Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32 Tff7b72== Te6edf3E_NOINTERFACETb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffThe specified class does not implement the requested interface, or the controlling IUnknown does not expose the requested interface.Ta5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32 Tff7b72== Te6edf3E_POINTERTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffAn argument is NULLTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32 Tff7b72== Te6edf3E_INVALIDARGTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid argumentTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32 Tff7b72== Te6edf3E_OUTOFMEMORYTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffOut of memoryTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32 Tff7b72== Te6edf3AUDCLNT_E_UNSUPPORTED_FORMATTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnsupported formatTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32 Tff7b72== Te6edf3CO_E_NOTINITIALIZEDTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffWindows COM context not initialized in Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffError Tffd700{}Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Tffa657hexTb4b4b4(Te6edf3hresultTff7b72+T79c0ff2Tff7b72*Tff7b72*T79c0ff32Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tf0883e@staticmethod
Tff7b72def Td2a8ffreleaseTb4b4b4(Te6edf3ppObjectTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3ppObjectTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72!= Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4:
Te6edf3ppObjectTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffReleaseTb4b4b4(Te6edf3ppObjectTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3ppObjectTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffNULL
Te6edf3_com Tff7b72= Te6edf3_COMLibraryTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffall_speakersTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffALL SPEAKERS Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e# if not tid() in com_thread_ids: _com.init_com()
Tff7b72with Te6edf3_DeviceEnumeratorTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3enumTb4b4b4:
Tff7b72return Tb4b4b4[Te6edf3_SpeakerTb4b4b4(Te6edf3devTb4b4b4) Tff7b72for Te6edf3dev Tff7b72in Te6edf3enumTff7b72.Td2a8ffall_devicesTb4b4b4(Ta5d6ff'Ta5d6ffspeakerTa5d6ff'Tb4b4b4)Tb4b4b4]
Tff7b72def Td2a8ffdefault_speakerTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDEFAULT SPEAKER Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e# if not tid() in com_thread_ids: _com.init_com()
Tff7b72with Te6edf3_DeviceEnumeratorTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3enumTb4b4b4:
Tff7b72return Te6edf3_SpeakerTb4b4b4(Te6edf3enumTff7b72.Td2a8ffdefault_deviceTb4b4b4(Ta5d6ff'Ta5d6ffspeakerTa5d6ff'Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffget_speakerTb4b4b4(Tffa657idTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffGET SPEAKER Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e# if not tid() in com_thread_ids: _com.init_com()
Tff7b72return Te6edf3_match_deviceTb4b4b4(Tffa657idTb4b4b4, Te6edf3all_speakersTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffall_microphonesTb4b4b4(Te6edf3include_loopbackTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffALL MICROPHONES Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e# if not tid() in com_thread_ids: _com.init_com()
Tff7b72with Te6edf3_DeviceEnumeratorTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3enumTb4b4b4:
Tff7b72if Te6edf3include_loopbackTb4b4b4:
Tff7b72return Tb4b4b4[Te6edf3_MicrophoneTb4b4b4(Te6edf3devTb4b4b4, Te6edf3isloopbackTff7b72=Tff7b72TrueTb4b4b4) Tff7b72for Te6edf3dev Tff7b72in Te6edf3enumTff7b72.Td2a8ffall_devicesTb4b4b4(Ta5d6ff'Ta5d6ffspeakerTa5d6ff'Tb4b4b4)Tb4b4b4] Tff7b72+ Tb4b4b4[Te6edf3_MicrophoneTb4b4b4(Te6edf3devTb4b4b4) Tff7b72for Te6edf3dev Tff7b72in Te6edf3enumTff7b72.Td2a8ffall_devicesTb4b4b4(Ta5d6ff'Ta5d6ffmicrophoneTa5d6ff'Tb4b4b4)Tb4b4b4]
Tff7b72elseTb4b4b4:
Tff7b72return Tb4b4b4[Te6edf3_MicrophoneTb4b4b4(Te6edf3devTb4b4b4) Tff7b72for Te6edf3dev Tff7b72in Te6edf3enumTff7b72.Td2a8ffall_devicesTb4b4b4(Ta5d6ff'Ta5d6ffmicrophoneTa5d6ff'Tb4b4b4)Tb4b4b4]
Tff7b72def Td2a8ffdefault_microphoneTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDEFAULT MICROPHONE Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e# if not tid() in com_thread_ids: _com.init_com()
Tff7b72with Te6edf3_DeviceEnumeratorTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3enumTb4b4b4:
Tff7b72return Te6edf3_MicrophoneTb4b4b4(Te6edf3enumTff7b72.Td2a8ffdefault_deviceTb4b4b4(Ta5d6ff'Ta5d6ffmicrophoneTa5d6ff'Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffget_microphoneTb4b4b4(Tffa657idTb4b4b4, Te6edf3include_loopbackTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffGET MICROPHONE Tffd700{Te6edf3tidTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e# if not tid() in com_thread_ids: _com.init_com()
Tff7b72return Te6edf3_match_deviceTb4b4b4(Tffa657idTb4b4b4, Te6edf3all_microphonesTb4b4b4(Te6edf3include_loopbackTb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ff_match_deviceTb4b4b4(Tffa657idTb4b4b4, Te6edf3devicesTb4b4b4)Tb4b4b4:
Te6edf3devices_by_id Tff7b72= Tb4b4b4{Te6edf3deviceTff7b72.Td2a8ffidTb4b4b4: Te6edf3device Tff7b72for Te6edf3device Tff7b72in Te6edf3devicesTb4b4b4}
Te6edf3devices_by_name Tff7b72= Tb4b4b4{Te6edf3deviceTff7b72.Td2a8ffnameTb4b4b4: Te6edf3device Tff7b72for Te6edf3device Tff7b72in Te6edf3devicesTb4b4b4}
Tff7b72if Tffa657id Tff7b72in Te6edf3devices_by_idTb4b4b4:
Tff7b72return Te6edf3devices_by_idTb4b4b4[Tffa657idTb4b4b4]
T8b949e# try substring match:
Tff7b72for Te6edf3nameTb4b4b4, Te6edf3device Tff7b72in Te6edf3devices_by_nameTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tffa657id Tff7b72in Te6edf3nameTb4b4b4:
Tff7b72return Te6edf3device
T8b949e# try fuzzy match:
Te6edf3pattern Tff7b72= Ta5d6ff'Ta5d6ff.*Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Tffa657idTb4b4b4)
Tff7b72for Te6edf3nameTb4b4b4, Te6edf3device Tff7b72in Te6edf3devices_by_nameTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3reTff7b72.Td2a8ffmatchTb4b4b4(Te6edf3patternTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3device
Tff7b72raise Tf85149IndexErrorTb4b4b4(Ta5d6ff'Ta5d6ffno device with id Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Tffa657idTb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ff_str2wstrTb4b4b4(Te6edf3stringTb4b4b4)Tb4b4b4:
T8b949e"""Converts a Python str to a Windows WSTR_T."""
Tff7b72return Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffint16_t[]Ta5d6ff'Tb4b4b4, Tb4b4b4[Tffa657ordTb4b4b4(Te6edf3sTb4b4b4) Tff7b72for Te6edf3s Tff7b72in Te6edf3stringTb4b4b4]Tff7b72+Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Tff7b72def Td2a8ff_guidofTb4b4b4(Te6edf3uuid_strTb4b4b4)Tb4b4b4:
T8b949e"""Creates a Windows LPIID from a str."""
Te6edf3IID Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffLPIIDTa5d6ff'Tb4b4b4)
T8b949e# convert to zero terminated wide string
Te6edf3uuid Tff7b72= Te6edf3_str2wstrTb4b4b4(Te6edf3uuid_strTb4b4b4)
Te6edf3hr Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffIIDFromStringTb4b4b4(Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffchar*Ta5d6ff"Tb4b4b4, Te6edf3uuidTb4b4b4)Tb4b4b4, Te6edf3IIDTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3IID
Tff7b72def Td2a8ffget_nameTb4b4b4(Tb4b4b4)Tb4b4b4: Tff7b72raise Tf85149NotImplementedErrorTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffset_nameTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4: Tff7b72raise Tf85149NotImplementedErrorTb4b4b4(Tb4b4b4)
Tff7b72class T56d364_DeviceEnumeratorTb4b4b4:
T8b949e"""Wrapper class for an IMMDeviceEnumerator**.
Provides methods for retrieving _Devices and pointers to the
underlying IMMDevices.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ptr Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIMMDeviceEnumerator **Ta5d6ff'Tb4b4b4)
Te6edf3IID_MMDeviceEnumerator Tff7b72= Te6edf3_guidofTb4b4b4(Ta5d6ff"Ta5d6ff{Ta5d6ffBCDE0395-E52F-467C-8E3D-C4579291692E}Ta5d6ff"Tb4b4b4)
Te6edf3IID_IMMDeviceEnumerator Tff7b72= Te6edf3_guidofTb4b4b4(Ta5d6ff"Ta5d6ff{Ta5d6ffA95664D2-9614-4F35-A746-DE8DB63617E6}Ta5d6ff"Tb4b4b4)
T8b949e# see shared/WTypesbase.h and um/combaseapi.h:
Te6edf3CLSCTX_ALL Tff7b72= T79c0ff23
Te6edf3hr Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffCoCreateInstanceTb4b4b4(Te6edf3IID_MMDeviceEnumeratorTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4, Te6edf3CLSCTX_ALLTb4b4b4,
Te6edf3IID_IMMDeviceEnumeratorTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffvoid **Ta5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4)Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72def Tff7b72__enter__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72self
Tff7b72def Tff7b72__exit__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3tracebackTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4)
Tff7b72def Tff7b72__del__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4)
Tff7b72def Td2a8ff_device_idTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3device_ptrTb4b4b4)Tb4b4b4:
Te6edf3ppId Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffLPWSTR *Ta5d6ff'Tb4b4b4)
Te6edf3hr Tff7b72= Te6edf3device_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetIdTb4b4b4(Te6edf3device_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3ppIdTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3_ffiTff7b72.Td2a8ffstringTb4b4b4(Te6edf3ppIdTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Tff7b72def Td2a8ffall_devicesTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3kindTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3kind Tff7b72== Ta5d6ff'Ta5d6ffspeakerTa5d6ff'Tb4b4b4: Te6edf3data_flow Tff7b72= T79c0ff0 T8b949e# render
Tff7b72elif Te6edf3kind Tff7b72== Ta5d6ff'Ta5d6ffmicrophoneTa5d6ff'Tb4b4b4: Te6edf3data_flow Tff7b72= T79c0ff1 T8b949e# capture
Tff7b72elseTb4b4b4: Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff'Ta5d6ffInvalid kind: Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3kindTb4b4b4)Tb4b4b4)
Te6edf3DEVICE_STATE_ACTIVE Tff7b72= T79c0ff0x1
Te6edf3ppDevices Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIMMDeviceCollection **Ta5d6ff'Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffEnumAudioEndpointsTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3data_flowTb4b4b4, Te6edf3DEVICE_STATE_ACTIVETb4b4b4, Te6edf3ppDevicesTb4b4b4)Tb4b4b4;
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72for Te6edf3ppDevice Tff7b72in Te6edf3_DeviceCollectionTb4b4b4(Te6edf3ppDevicesTb4b4b4)Tb4b4b4:
Te6edf3device Tff7b72= Te6edf3_DeviceTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_device_idTb4b4b4(Te6edf3ppDeviceTb4b4b4)Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ppDeviceTb4b4b4)
Tff7b72yield Te6edf3device
Tff7b72def Td2a8ffdefault_deviceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3kindTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3kind Tff7b72== Ta5d6ff'Ta5d6ffspeakerTa5d6ff'Tb4b4b4: Te6edf3data_flow Tff7b72= T79c0ff0 T8b949e# render
Tff7b72elif Te6edf3kind Tff7b72== Ta5d6ff'Ta5d6ffmicrophoneTa5d6ff'Tb4b4b4: Te6edf3data_flow Tff7b72= T79c0ff1 T8b949e# capture
Tff7b72elseTb4b4b4: Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff'Ta5d6ffInvalid kind: Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3kindTb4b4b4)Tb4b4b4)
Te6edf3ppDevice Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIMMDevice **Ta5d6ff'Tb4b4b4)
Te6edf3eConsole Tff7b72= T79c0ff0
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetDefaultAudioEndpointTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3data_flowTb4b4b4, Te6edf3eConsoleTb4b4b4, Te6edf3ppDeviceTb4b4b4)Tb4b4b4;
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Te6edf3device Tff7b72= Te6edf3_DeviceTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_device_idTb4b4b4(Te6edf3ppDeviceTb4b4b4)Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ppDeviceTb4b4b4)
Tff7b72return Te6edf3device
Tff7b72def Td2a8ffdevice_ptrTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3devidTb4b4b4)Tb4b4b4:
T8b949e"""Retrieve IMMDevice** for a WASAPI device ID."""
Te6edf3ppDevice Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIMMDevice **Ta5d6ff'Tb4b4b4)
Te6edf3devid Tff7b72= Te6edf3_str2wstrTb4b4b4(Te6edf3devidTb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetDeviceTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff'Ta5d6ffwchar_t *Ta5d6ff'Tb4b4b4, Te6edf3devidTb4b4b4)Tb4b4b4, Te6edf3ppDeviceTb4b4b4)Tb4b4b4;
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3ppDevice
Tff7b72class T56d364_DeviceCollectionTb4b4b4:
T8b949e"""Wrapper class for an IMMDeviceCollection**.
Generator for IMMDevice** pointers.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3ptrTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ptr Tff7b72= Te6edf3ptr
Tff7b72def Tff7b72__del__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4)
Tff7b72def Tff7b72__len__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pCount Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffUINT *Ta5d6ff'Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetCountTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3pCountTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3pCountTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72def Tff7b72__getitem__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3idxTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3idx Tff7b72>Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149StopIterationTb4b4b4(Tb4b4b4)
Te6edf3ppDevice Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIMMDevice **Ta5d6ff'Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffItemTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3idxTb4b4b4, Te6edf3ppDeviceTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3ppDevice
Tff7b72class T56d364_PropVariantTb4b4b4:
T8b949e"""Wrapper class for a PROPVARIANT.
Correctly allocates and frees a PROPVARIANT. Normal CFFI
malloc/free is incompatible with PROPVARIANTs, since COM expects
PROPVARIANTS to be freely reallocatable by its own allocator.
Access the PROPVARIANT* pointer using .ptr.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptr Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffCoTaskMemAllocTb4b4b4(Te6edf3_ffiTff7b72.Td2a8ffsizeofTb4b4b4(Ta5d6ff'Ta5d6ffPROPVARIANTTa5d6ff'Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffptr Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffPROPVARIANT *Ta5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffptrTb4b4b4)
Tff7b72def Tff7b72__del__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3hr Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffPropVariantClearTb4b4b4(Tff7b72selfTff7b72.Td2a8ffptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72class T56d364_DeviceTb4b4b4:
T8b949e"""Wrapper class for an IMMDevice.
Implements memory management and retrieval of the device name, the
number of channels, and device activation.
Subclassed by _Speaker and _Microphone for playback and recording.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Tffa657idTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_id Tff7b72= Tffa657id
Tff7b72def Td2a8ff_device_ptrTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3_DeviceEnumeratorTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3enumTb4b4b4:
Tff7b72return Te6edf3enumTff7b72.Td2a8ffdevice_ptrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_idTb4b4b4)
Tf0883e@property
Tff7b72def Td2a8ffidTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_id
Tf0883e@property
Tff7b72def Td2a8ffnameTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# um/coml2api.h:
Te6edf3ppPropertyStore Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIPropertyStore **Ta5d6ff'Tb4b4b4)
Te6edf3ptr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_device_ptrTb4b4b4(Tb4b4b4)
Te6edf3hr Tff7b72= Te6edf3ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffOpenPropertyStoreTb4b4b4(Te6edf3ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3ppPropertyStoreTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Te6edf3propvariant Tff7b72= Te6edf3_PropVariantTb4b4b4(Tb4b4b4)
T8b949e# um/functiondiscoverykeys_devpkey.h and https://msdn.microsoft.com/en-us/library/windows/desktop/dd370812(v=vs.85).aspx
Te6edf3PKEY_Device_FriendlyName Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffPROPERTYKEY *Ta5d6ff"Tb4b4b4,
Tb4b4b4[Tb4b4b4[T79c0ff0xa45c254eTb4b4b4, T79c0ff0xdf1cTb4b4b4, T79c0ff0x4efdTb4b4b4, Tb4b4b4[T79c0ff0x80Tb4b4b4, T79c0ff0x20Tb4b4b4, T79c0ff0x67Tb4b4b4, T79c0ff0xd1Tb4b4b4, T79c0ff0x46Tb4b4b4, T79c0ff0xa8Tb4b4b4, T79c0ff0x50Tb4b4b4, T79c0ff0xe0Tb4b4b4]Tb4b4b4]Tb4b4b4,
T79c0ff14Tb4b4b4]Tb4b4b4)
Te6edf3hr Tff7b72= Te6edf3ppPropertyStoreTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetValueTb4b4b4(Te6edf3ppPropertyStoreTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3PKEY_Device_FriendlyNameTb4b4b4, Te6edf3propvariantTff7b72.Td2a8ffptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72if Te6edf3propvariantTff7b72.Td2a8ffptrTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffvt Tff7b72!= T79c0ff31Tb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff'Ta5d6ffProperty was expected to be a string, but is not a stringTa5d6ff'Tb4b4b4)
Te6edf3data Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffshort*Ta5d6ff"Tb4b4b4, Te6edf3propvariantTff7b72.Td2a8ffptrTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffdataTb4b4b4)
Tff7b72for Te6edf3idx Tff7b72in Tffa657rangeTb4b4b4(T79c0ff256Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3dataTb4b4b4[Te6edf3idxTb4b4b4] Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72break
Te6edf3devicename Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ffhTa5d6ff' Tff7b72* Te6edf3idxTb4b4b4, Tff7b72*Te6edf3dataTb4b4b4[T79c0ff0Tb4b4b4:Te6edf3idxTb4b4b4]Tb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff'Ta5d6ffutf-16Ta5d6ff'Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ppPropertyStoreTb4b4b4)
Tff7b72return Te6edf3devicename
Tf0883e@property
Tff7b72def Td2a8ffchannelsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# um/coml2api.h:
Te6edf3ppPropertyStore Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffIPropertyStore **Ta5d6ff'Tb4b4b4)
Te6edf3ptr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_device_ptrTb4b4b4(Tb4b4b4)
Te6edf3hr Tff7b72= Te6edf3ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffOpenPropertyStoreTb4b4b4(Te6edf3ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3ppPropertyStoreTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Te6edf3propvariant Tff7b72= Te6edf3_PropVariantTb4b4b4(Tb4b4b4)
T8b949e# um/functiondiscoverykeys_devpkey.h and https://msdn.microsoft.com/en-us/library/windows/desktop/dd370812(v=vs.85).aspx
Te6edf3PKEY_AudioEngine_DeviceFormat Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffPROPERTYKEY *Ta5d6ff"Tb4b4b4,
Tb4b4b4[Tb4b4b4[T79c0ff0xf19f064dTb4b4b4, T79c0ff0x82cTb4b4b4, T79c0ff0x4e27Tb4b4b4, Tb4b4b4[T79c0ff0xbcTb4b4b4, T79c0ff0x73Tb4b4b4, T79c0ff0x68Tb4b4b4, T79c0ff0x82Tb4b4b4, T79c0ff0xa1Tb4b4b4, T79c0ff0xbbTb4b4b4, T79c0ff0x8eTb4b4b4, T79c0ff0x4cTb4b4b4]Tb4b4b4]Tb4b4b4,
T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3hr Tff7b72= Te6edf3ppPropertyStoreTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetValueTb4b4b4(Te6edf3ppPropertyStoreTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3PKEY_AudioEngine_DeviceFormatTb4b4b4, Te6edf3propvariantTff7b72.Td2a8ffptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ppPropertyStoreTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72if Te6edf3propvariantTff7b72.Td2a8ffptrTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffvt Tff7b72!= T79c0ff65Tb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff'Ta5d6ffProperty was expected to be a blob, but is not a blobTa5d6ff'Tb4b4b4)
Te6edf3pPropVariantBlob Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffBLOB_PROPVARIANT *Ta5d6ff"Tb4b4b4, Te6edf3propvariantTff7b72.Td2a8ffptrTb4b4b4)
Tff7b72assert Te6edf3pPropVariantBlobTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffblobTff7b72.Td2a8ffcbSize Tff7b72== T79c0ff40
Te6edf3waveformat Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffWAVEFORMATEX *Ta5d6ff"Tb4b4b4, Te6edf3pPropVariantBlobTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffblobTff7b72.Td2a8ffpBlobDataTb4b4b4)
Te6edf3channels Tff7b72= Te6edf3waveformatTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffnChannels
Tff7b72return Te6edf3channels
Tff7b72def Td2a8ff_audio_clientTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3CLSCTX_ALL Tff7b72= T79c0ff23
Te6edf3ppAudioClient Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffIAudioClient **Ta5d6ff"Tb4b4b4)
Te6edf3IID_IAudioClient Tff7b72= Te6edf3_guidofTb4b4b4(Ta5d6ff"Ta5d6ff{Ta5d6ff1CB9AD4C-DBFA-4C32-B178-C2F568A703B2}Ta5d6ff"Tb4b4b4)
Te6edf3ptr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_device_ptrTb4b4b4(Tb4b4b4)
Te6edf3hr Tff7b72= Te6edf3ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffActivateTb4b4b4(Te6edf3ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3IID_IAudioClientTb4b4b4, Te6edf3CLSCTX_ALLTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffvoid**Ta5d6ff"Tb4b4b4, Te6edf3ppAudioClientTb4b4b4)Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Te6edf3ptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3ppAudioClient
Tff7b72class T56d364_SpeakerTb4b4b4(Te6edf3_DeviceTb4b4b4)Tb4b4b4:
T8b949e"""A soundcard output. Can be used to play audio.
Use the `play` method to play one piece of audio, or use the
`player` method to get a context manager for playing continuous
audio.
Properties:
- `channels`: the number of available channels.
- `name`: the name of the sound card.
- `id`: the WASAPI ID of the sound card.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3deviceTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_id Tff7b72= Te6edf3deviceTff7b72.Td2a8ff_id
Tff7b72def Tff7b72__repr__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff'Ta5d6ff<Speaker Tffd700{}Ta5d6ff (Tffd700{}Ta5d6ff channels)>Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4,Tff7b72selfTff7b72.Td2a8ffchannelsTb4b4b4)
Tff7b72def Td2a8ffplayerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTff7b72=Tff7b72NoneTb4b4b4, Te6edf3blocksizeTff7b72=Tff7b72NoneTb4b4b4, Te6edf3exclusive_modeTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3channels Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3channels Tff7b72= Tff7b72selfTff7b72.Td2a8ffchannels
Tff7b72return Te6edf3_PlayerTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_audio_clientTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTb4b4b4, Te6edf3blocksizeTb4b4b4, Tff7b72FalseTb4b4b4, Te6edf3exclusive_modeTb4b4b4)
Tff7b72def Td2a8ffplayTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTff7b72=Tff7b72NoneTb4b4b4, Te6edf3blocksizeTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ffplayerTb4b4b4(Te6edf3samplerateTb4b4b4, Te6edf3channelsTb4b4b4, Te6edf3blocksizeTb4b4b4) Tff7b72as Te6edf3pTb4b4b4:
Te6edf3pTff7b72.Td2a8ffplayTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72class T56d364_MicrophoneTb4b4b4(Te6edf3_DeviceTb4b4b4)Tb4b4b4:
T8b949e"""A soundcard input. Can be used to record audio.
Use the `record` method to record one piece of audio, or use the
`recorder` method to get a context manager for recording
continuous audio.
Properties:
- `channels`: the number of available channels.
- `name`: the name of the sound card.
- `id`: the WASAPI ID of the sound card.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3deviceTb4b4b4, Te6edf3isloopbackTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_id Tff7b72= Te6edf3deviceTff7b72.Td2a8ff_id
Tff7b72selfTff7b72.Td2a8ffisloopback Tff7b72= Te6edf3isloopback
Tff7b72def Tff7b72__repr__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffisloopbackTb4b4b4:
Tff7b72return Ta5d6ff'Ta5d6ff<Loopback Tffd700{}Ta5d6ff (Tffd700{}Ta5d6ff channels)>Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4,Tff7b72selfTff7b72.Td2a8ffchannelsTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72return Ta5d6ff'Ta5d6ff<Microphone Tffd700{}Ta5d6ff (Tffd700{}Ta5d6ff channels)>Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4,Tff7b72selfTff7b72.Td2a8ffchannelsTb4b4b4)
Tff7b72def Td2a8ffrecorderTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTff7b72=Tff7b72NoneTb4b4b4, Te6edf3blocksizeTff7b72=Tff7b72NoneTb4b4b4, Te6edf3exclusive_modeTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3channels Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3channels Tff7b72= Tff7b72selfTff7b72.Td2a8ffchannels
Tff7b72return Te6edf3_RecorderTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_audio_clientTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTb4b4b4, Te6edf3blocksizeTb4b4b4, Tff7b72selfTff7b72.Td2a8ffisloopbackTb4b4b4, Te6edf3exclusive_modeTb4b4b4)
Tff7b72def Td2a8ffrecordTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3numframesTb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTff7b72=Tff7b72NoneTb4b4b4, Te6edf3blocksizeTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ffrecorderTb4b4b4(Te6edf3samplerateTb4b4b4, Te6edf3channelsTb4b4b4, Te6edf3blocksizeTb4b4b4) Tff7b72as Te6edf3rTb4b4b4:
Tff7b72return Te6edf3rTff7b72.Td2a8ffrecordTb4b4b4(Te6edf3numframesTb4b4b4)
Tff7b72class T56d364_AudioClientTb4b4b4:
T8b949e"""Wrapper class for an IAudioClient** object.
Implements memory management and various property retrieval for
IAudioClient objects.
Subclassed by _Player and _Recorder for playback and recording.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3ptrTb4b4b4, Te6edf3samplerateTb4b4b4, Te6edf3channelsTb4b4b4, Te6edf3blocksizeTb4b4b4, Te6edf3isloopbackTb4b4b4, Te6edf3exclusive_modeTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_ptr Tff7b72= Te6edf3ptr
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3channelsTb4b4b4, Tffa657intTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffchannelmap Tff7b72= Tffa657listTb4b4b4(Tffa657rangeTb4b4b4(Te6edf3channelsTb4b4b4)Tb4b4b4)
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3channelsTb4b4b4, Te6edf3collectionsTff7b72.Td2a8ffabcTff7b72.Td2a8ffIterableTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffchannelmap Tff7b72= Te6edf3channels
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff'Ta5d6ffchannels must be iterable or integerTa5d6ff'Tb4b4b4)
Tff7b72if Tffa657listTb4b4b4(Tffa657rangeTb4b4b4(Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4) Tff7b72!= Tffa657sortedTb4b4b4(Tffa657listTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff'Ta5d6ffDue to limitations of WASAPI, channel maps on Windows Ta5d6ff'
Ta5d6ff'Ta5d6ffmust be a combination of `range(0, x)`.Ta5d6ff'Tb4b4b4)
Tff7b72if Te6edf3blocksize Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3blocksize Tff7b72= Tff7b72selfTff7b72.Td2a8ffdeviceperiodTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72*Te6edf3samplerate
Te6edf3ppMixFormat Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffWAVEFORMATEXTENSIBLE**Ta5d6ff'Tb4b4b4) T8b949e# See: https://docs.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-waveformatextensible
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetMixFormatTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3ppMixFormatTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
T8b949e# It's a WAVEFORMATEXTENSIBLE with room for KSDATAFORMAT_SUBTYPE_IEEE_FLOAT:
T8b949e# Note: Some devices may not return 0xFFFE format, but WASAPI should handle conversion
Tff7b72if Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffwFormatTag Tff7b72== T79c0ff0xFFFETb4b4b4:
Tff7b72assert Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffcbSize Tff7b72== T79c0ff22
T8b949e# The data format is float32:
T8b949e# These values were found empirically, and I don't know why they work.
T8b949e# The program crashes if these values are different
Tff7b72assert Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffSubFormatTff7b72.Td2a8ffData1 Tff7b72== T79c0ff0x100000
Tff7b72assert Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffSubFormatTff7b72.Td2a8ffData2 Tff7b72== T79c0ff0x0080
Tff7b72assert Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffSubFormatTff7b72.Td2a8ffData3 Tff7b72== T79c0ff0xaa00
Tff7b72assert Tb4b4b4[Tffa657intTb4b4b4(Te6edf3xTb4b4b4) Tff7b72for Te6edf3x Tff7b72in Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffSubFormatTff7b72.Td2a8ffData4Tb4b4b4[T79c0ff0Tb4b4b4:T79c0ff4Tb4b4b4]Tb4b4b4] Tff7b72== Tb4b4b4[T79c0ff0Tb4b4b4, T79c0ff56Tb4b4b4, T79c0ff155Tb4b4b4, T79c0ff113Tb4b4b4]
T8b949e# the last four bytes seem to vary randomly
Tff7b72elseTb4b4b4:
T8b949e# Device doesn't return WAVEFORMATEXTENSIBLE, but WASAPI will handle conversion
T8b949e# Just skip the assertions and let WASAPI convert
Tff7b72pass
Te6edf3channels Tff7b72= Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)
Te6edf3channelmask Tff7b72= T79c0ff0
Tff7b72for Te6edf3ch Tff7b72in Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4:
Te6edf3channelmask Tff7b72|Tff7b72= T79c0ff1Tff7b72<<Te6edf3ch
Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffnChannelsTff7b72=Te6edf3channels
Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffnSamplesPerSecTff7b72=Tffa657intTb4b4b4(Te6edf3samplerateTb4b4b4)
Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffnAvgBytesPerSecTff7b72=Tffa657intTb4b4b4(Te6edf3samplerateTb4b4b4) Tff7b72* Te6edf3channels Tff7b72* T79c0ff4
Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffnBlockAlignTff7b72=Te6edf3channels Tff7b72* T79c0ff4
Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffFormatTff7b72.Td2a8ffwBitsPerSampleTff7b72=T79c0ff32
Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffSamplesTff7b72=Tffa657dictTb4b4b4(Te6edf3wValidBitsPerSampleTff7b72=T79c0ff32Tb4b4b4)
T8b949e# does not work:
T8b949e# ppMixFormat[0][0].dwChannelMask=channelmask
T8b949e# See: https://docs.microsoft.com/en-us/windows/win32/coreaudio/exclusive-mode-streams
T8b949e# nopersist, see: https://docs.microsoft.com/en-us/windows/win32/coreaudio/audclnt-streamflags-xxx-constants
Te6edf3streamflags Tff7b72= T79c0ff0x00080000
Tff7b72if Te6edf3exclusive_modeTb4b4b4:
Te6edf3sharemode Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffAUDCLNT_SHAREMODE_EXCLUSIVE
Te6edf3periodicity Tff7b72= T79c0ff0 T8b949e# 0 uses default, must set value if using AUDCLNT_STREAMFLAGS_EVENTCALLBACK (0x00040000)
Tff7b72if Te6edf3isloopbackTb4b4b4: Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffLoopback mode and exclusive mode are incompatible.Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3sharemode Tff7b72= Te6edf3_ole32Tff7b72.Td2a8ffAUDCLNT_SHAREMODE_SHARED
T8b949e# resample | remix | better-SRC
T8b949e# rateadjust | autoconvPCM | SRC default quality
Te6edf3streamflags Tff7b72|Tff7b72= T79c0ff0x00100000 Tff7b72| T79c0ff0x80000000 Tff7b72| T79c0ff0x08000000 T8b949e# These flags are only relevant/permitted for shared mode
Te6edf3periodicity Tff7b72= T79c0ff0 T8b949e# Always 0 for shared mode
Tff7b72if Te6edf3isloopbackTb4b4b4: Te6edf3streamflags Tff7b72|Tff7b72= T79c0ff0x00020000 T8b949e# Loopback only allowed for shared mode
Te6edf3bufferduration Tff7b72= Tffa657intTb4b4b4(Te6edf3blocksizeTff7b72/Te6edf3samplerate Tff7b72* T79c0ff10000000Tb4b4b4) T8b949e# in hecto-nanoseconds (1000_000_0)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffInitializeTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3sharemodeTb4b4b4, Te6edf3streamflagsTb4b4b4, Te6edf3bufferdurationTb4b4b4, Te6edf3periodicityTb4b4b4, Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Te6edf3_ole32Tff7b72.Td2a8ffCoTaskMemFreeTb4b4b4(Te6edf3ppMixFormatTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
T8b949e# save samplerate for later
Tff7b72selfTff7b72.Td2a8ffsamplerate Tff7b72= Te6edf3samplerate
T8b949e# placeholder for the last time we had audio input available
Tff7b72selfTff7b72.Td2a8ff_idle_start_time Tff7b72= Tff7b72None
Tf0883e@property
Tff7b72def Td2a8ffbuffersizeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pBufferSize Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffUINT32*Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetBufferSizeTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3pBufferSizeTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3pBufferSizeTb4b4b4[T79c0ff0Tb4b4b4]
Tf0883e@property
Tff7b72def Td2a8ffdeviceperiodTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pDefaultPeriod Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffREFERENCE_TIME*Ta5d6ff"Tb4b4b4)
Te6edf3pMinimumPeriod Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffREFERENCE_TIME*Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetDevicePeriodTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3pDefaultPeriodTb4b4b4, Te6edf3pMinimumPeriodTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3pDefaultPeriodTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72/T79c0ff10_000_000Tb4b4b4, Te6edf3pMinimumPeriodTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72/T79c0ff10_000_000
Tf0883e@property
Tff7b72def Td2a8ffcurrentpaddingTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pPadding Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffUINT32*Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetCurrentPaddingTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3pPaddingTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3pPaddingTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72class T56d364_PlayerTb4b4b4(Te6edf3_AudioClientTb4b4b4)Tb4b4b4:
T8b949e"""A context manager for an active output stream.
Audio playback is available as soon as the context manager is
entered. Audio data can be played using the `play` method.
Successive calls to `play` will queue up the audio one piece after
another. If no audio is queued up, this will play silence.
This context manager can only be entered once, and can not be used
after it is closed.
"""
T8b949e# https://msdn.microsoft.com/en-us/library/windows/desktop/dd316756(v=vs.85).aspx
Tff7b72def Td2a8ff_render_clientTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3iid Tff7b72= Te6edf3_guidofTb4b4b4(Ta5d6ff"Ta5d6ff{Ta5d6ffF294ACFC-3146-4483-A7BF-ADDCA7C260E2}Ta5d6ff"Tb4b4b4)
Te6edf3ppRenderClient Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffIAudioRenderClient**Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetServiceTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3iidTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffvoid**Ta5d6ff"Tb4b4b4, Te6edf3ppRenderClientTb4b4b4)Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3ppRenderClient
Tff7b72def Td2a8ff_render_bufferTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3numframesTb4b4b4)Tb4b4b4:
Te6edf3data Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffBYTE**Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ppRenderClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetBufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppRenderClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3numframesTb4b4b4, Te6edf3dataTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3data
Tff7b72def Td2a8ff_render_releaseTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3numframesTb4b4b4)Tb4b4b4:
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ppRenderClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffReleaseBufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppRenderClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3numframesTb4b4b4, T79c0ff0Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72def Td2a8ff_render_available_framesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffbuffersizeTff7b72-Tff7b72selfTff7b72.Td2a8ffcurrentpadding
Tff7b72def Tff7b72__enter__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ppRenderClient Tff7b72= Tff7b72selfTff7b72.Td2a8ff_render_clientTb4b4b4(Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffStartTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Tff7b72self
Tff7b72def Tff7b72__exit__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3tracebackTb4b4b4)Tb4b4b4:
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffStopTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppRenderClientTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffrelease_comTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffplayTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e"""Play some audio data.
Internally, all data is handled as float32 and with the
appropriate number of channels. For maximum performance,
provide data as a `frames x channels` float32 numpy array.
If single-channel or one-dimensional data is given, this data
will be played on all available channels.
This function will return *before* all data has been played,
so that additional data can be provided for gapless playback.
The amount of buffering can be controlled through the
blocksize of the player object.
If data is provided faster than it is played, later pieces
will be queued up and played one after another.
"""
Te6edf3data Tff7b72= Te6edf3numpyTff7b72.Td2a8ffarrayTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4, Te6edf3orderTff7b72=Ta5d6ff'Ta5d6ffCTa5d6ff'Tb4b4b4)
Tff7b72if Te6edf3dataTff7b72.Td2a8ffndim Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3data Tff7b72= Te6edf3dataTb4b4b4[Tb4b4b4:Tb4b4b4, Tff7b72NoneTb4b4b4] T8b949e# force 2d
Tff7b72if Te6edf3dataTff7b72.Td2a8ffndim Tff7b72!= T79c0ff2Tb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff'Ta5d6ffdata must be 1d or 2d, not Tffd700{}Ta5d6ffdTa5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3dataTff7b72.Td2a8ffndimTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3dataTff7b72.Td2a8ffshapeTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72== T79c0ff1 Tff7b72and Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff1Tb4b4b4:
Te6edf3data Tff7b72= Te6edf3numpyTff7b72.Td2a8fftileTb4b4b4(Te6edf3dataTb4b4b4, Tb4b4b4[T79c0ff1Tb4b4b4, Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4]Tb4b4b4)
T8b949e# internally, channel numbers are always ascending:
Te6edf3sortidx Tff7b72= Tffa657sortedTb4b4b4(Tffa657rangeTb4b4b4(Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3kTb4b4b4: Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4[Te6edf3kTb4b4b4]Tb4b4b4)
Te6edf3data Tff7b72= Te6edf3dataTb4b4b4[Tb4b4b4:Tb4b4b4, Te6edf3sortidxTb4b4b4]
Tff7b72if Te6edf3dataTff7b72.Td2a8ffshapeTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72!= Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff'Ta5d6ffsecond dimension of data must be equal to the number of channels, not Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3dataTff7b72.Td2a8ffshapeTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4)
Tff7b72while Te6edf3dataTff7b72.Td2a8ffnbytes Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3towrite Tff7b72= Tff7b72selfTff7b72.Td2a8ff_render_available_framesTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3towrite Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.001Tb4b4b4)
Tff7b72continue
Tffa657bytes Tff7b72= Te6edf3dataTb4b4b4[Tb4b4b4:Te6edf3towriteTb4b4b4]Tff7b72.Td2a8ffravelTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fftobytesTb4b4b4(Tb4b4b4)
Te6edf3buffer Tff7b72= Tff7b72selfTff7b72.Td2a8ff_render_bufferTb4b4b4(Te6edf3towriteTb4b4b4)
Te6edf3_ffiTff7b72.Td2a8ffmemmoveTb4b4b4(Te6edf3bufferTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Tffa657bytesTb4b4b4, Tffa657lenTb4b4b4(Tffa657bytesTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_render_releaseTb4b4b4(Te6edf3towriteTb4b4b4)
Te6edf3data Tff7b72= Te6edf3dataTb4b4b4[Te6edf3towriteTb4b4b4:Tb4b4b4]
Tff7b72class T56d364_RecorderTb4b4b4(Te6edf3_AudioClientTb4b4b4)Tb4b4b4:
T8b949e# https://msdn.microsoft.com/en-us/library/windows/desktop/dd370800(v=vs.85).aspx
Tff7b72def Td2a8ff_capture_clientTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3iid Tff7b72= Te6edf3_guidofTb4b4b4(Ta5d6ff"Ta5d6ff{Ta5d6ffC8ADBD64-E71E-48a0-A4DE-185C395CD317}Ta5d6ff"Tb4b4b4)
Te6edf3ppCaptureClient Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffIAudioCaptureClient**Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetServiceTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3iidTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffcastTb4b4b4(Ta5d6ff"Ta5d6ffvoid**Ta5d6ff"Tb4b4b4, Te6edf3ppCaptureClientTb4b4b4)Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3ppCaptureClient
Tff7b72def Td2a8ff_capture_bufferTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3data Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffBYTE**Ta5d6ff"Tb4b4b4)
Te6edf3toread Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffUINT32*Ta5d6ff'Tb4b4b4)
Te6edf3flags Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff'Ta5d6ffDWORD*Ta5d6ff'Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetBufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3dataTb4b4b4, Te6edf3toreadTb4b4b4, Te6edf3flagsTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4, Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3dataTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3toreadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3flagsTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72def Td2a8ff_capture_releaseTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3numframesTb4b4b4)Tb4b4b4:
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffReleaseBufferTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3numframesTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72def Td2a8ff_capture_available_framesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pSize Tff7b72= Te6edf3_ffiTff7b72.Td2a8ffnewTb4b4b4(Ta5d6ff"Ta5d6ffUINT32*Ta5d6ff"Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffGetNextPacketSizeTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3pSizeTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72return Te6edf3pSizeTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72def Tff7b72__enter__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3_comTff7b72.Td2a8ffinit_comTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ppCaptureClient Tff7b72= Tff7b72selfTff7b72.Td2a8ff_capture_clientTb4b4b4(Tb4b4b4)
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffStartTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_pending_chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_is_first_frame Tff7b72= Tff7b72True
Tff7b72return Tff7b72self
Tff7b72def Tff7b72__exit__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3tracebackTb4b4b4)Tb4b4b4:
Te6edf3hr Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8fflpVtblTff7b72.Td2a8ffStopTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3_comTff7b72.Td2a8ffcheck_errorTb4b4b4(Te6edf3hrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ppCaptureClientTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffreleaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_ptrTb4b4b4)
Te6edf3_comTff7b72.Td2a8ffrelease_comTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_record_chunkTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Record one chunk of audio data, as returned by WASAPI
The data will be returned as a 1D numpy array, which will be used by
the `record` method. This function is the interface of the `_Recorder`
object with WASAPI.
"""
Tff7b72while Tff7b72selfTff7b72.Td2a8ff_capture_available_framesTb4b4b4(Tb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
T8b949e# some sound cards indicate silence by not making any
T8b949e# frames available. If that is the case, we need to
T8b949e# estimate the number of zeros to return, by measuring the
T8b949e# silent time:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_idle_start_time Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_idle_start_time Tff7b72= Te6edf3timeTff7b72.Td2a8ffperf_counter_nsTb4b4b4(Tb4b4b4)
Te6edf3default_block_lengthTb4b4b4, Te6edf3minimum_block_length Tff7b72= Tff7b72selfTff7b72.Td2a8ffdeviceperiod
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3minimum_block_lengthTff7b72/T79c0ff4Tb4b4b4)
Te6edf3elapsed_time_ns Tff7b72= Te6edf3timeTff7b72.Td2a8ffperf_counter_nsTb4b4b4(Tb4b4b4) Tff7b72- Tff7b72selfTff7b72.Td2a8ff_idle_start_time
T8b949e# waiting times shorter than a block length or so are
T8b949e# normal, and not indicative of a silent sound card. If
T8b949e# the waiting times get longer however, we must assume
T8b949e# that there is no audio data forthcoming, and return
T8b949e# zeros instead:
Tff7b72if Te6edf3elapsed_time_ns Tff7b72/ T79c0ff1_000_000_000 Tff7b72> Te6edf3default_block_length Tff7b72* T79c0ff4Tb4b4b4:
Te6edf3num_frames Tff7b72= Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsamplerate Tff7b72* Te6edf3elapsed_time_ns Tff7b72/ T79c0ff1_000_000_000Tb4b4b4)
Te6edf3num_channels Tff7b72= Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_idle_start_time Tff7b72+Tff7b72= Te6edf3elapsed_time_ns
Tff7b72return Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Tb4b4b4[Te6edf3num_frames Tff7b72* Te6edf3num_channelsTb4b4b4]Tb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_idle_start_time Tff7b72= Tff7b72None
Te6edf3data_ptrTb4b4b4, Te6edf3nframesTb4b4b4, Te6edf3flags Tff7b72= Tff7b72selfTff7b72.Td2a8ff_capture_bufferTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3data_ptr Tff7b72!= Te6edf3_ffiTff7b72.Td2a8ffNULLTb4b4b4:
T8b949e# Convert the raw CFFI buffer into a standard bytes object to ensure compatibility
T8b949e# with modern NumPy versions (fromstring binary mode was removed). Using frombuffer
T8b949e# on bytes plus .copy() guarantees a writable float32 array for downstream processing.
Te6edf3buf Tff7b72= Tffa657bytesTb4b4b4(Te6edf3_ffiTff7b72.Td2a8ffbufferTb4b4b4(Te6edf3data_ptrTb4b4b4, Te6edf3nframes Tff7b72* T79c0ff4 Tff7b72* Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8fffrombufferTb4b4b4(Te6edf3bufTb4b4b4, Te6edf3dtypeTff7b72=Te6edf3numpyTff7b72.Td2a8fffloat32Tb4b4b4)Tff7b72.Td2a8ffcopyTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff'Ta5d6ffCould not create capture bufferTa5d6ff'Tb4b4b4)
Tff7b72if Te6edf3flags Tff7b72& Te6edf3_ole32Tff7b72.Td2a8ffAUDCLNT_BUFFERFLAGS_SILENTTb4b4b4:
T8b949e# see https://learn.microsoft.com/en-us/windows/win32/api/audioclient/ne-audioclient-_audclnt_bufferflags
Te6edf3chunkTb4b4b4[Tb4b4b4:Tb4b4b4] Tff7b72= T79c0ff0
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_is_first_frameTb4b4b4:
T8b949e# on first run, clear data discontinuity error, as it will always be set:
Te6edf3flags Tff7b72&Tff7b72= Tff7b72~Te6edf3_ole32Tff7b72.Td2a8ffAUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY
Tff7b72selfTff7b72.Td2a8ff_is_first_frame Tff7b72= Tff7b72False
Tff7b72if Te6edf3flags Tff7b72& Te6edf3_ole32Tff7b72.Td2a8ffAUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITYTb4b4b4:
T8b949e# TODO: Disable this warning
T8b949e# warnings.warn("data discontinuity in recording", SoundcardRuntimeWarning)
Tff7b72pass
T8b949e# ignore _ole32.AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR, since we don't use
T8b949e# time stamps.
Tff7b72if Te6edf3nframes Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_capture_releaseTb4b4b4(Te6edf3nframesTb4b4b4)
Tff7b72return Te6edf3chunk
Tff7b72elseTb4b4b4:
Tff7b72return Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Tff7b72def Td2a8ffrecordTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3numframesTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""Record a block of audio data.
The data will be returned as a frames × channels float32 numpy array.
This function will wait until numframes frames have been recorded.
If numframes is given, it will return exactly `numframes` frames,
and buffer the rest for later.
If numframes is None, it will return whatever the audio backend
has available right now.
Use this if latency must be kept to a minimum, but be aware that
block sizes can change at the whims of the audio backend.
If using `record` with `numframes=None` after using `record` with a
required `numframes`, the last buffered frame will be returned along
with the new recorded block.
(If you want to empty the last buffered frame instead, use `flush`)
"""
Tff7b72if Te6edf3numframes Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3recorded_data Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ff_pending_chunkTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_record_chunkTb4b4b4(Tb4b4b4)Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_pending_chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3recorded_frames Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_pending_chunkTb4b4b4)
Te6edf3recorded_data Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ff_pending_chunkTb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_pending_chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Te6edf3required_frames Tff7b72= Te6edf3numframesTff7b72*Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)
Tff7b72while Te6edf3recorded_frames Tff7b72< Te6edf3required_framesTb4b4b4:
Te6edf3chunk Tff7b72= Tff7b72selfTff7b72.Td2a8ff_record_chunkTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3chunkTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
T8b949e# no data forthcoming: return zeros
Te6edf3chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Te6edf3required_framesTff7b72-Te6edf3recorded_framesTb4b4b4,
Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Te6edf3recorded_dataTff7b72.Td2a8ffappendTb4b4b4(Te6edf3chunkTb4b4b4)
Te6edf3recorded_frames Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3chunkTb4b4b4)
Tff7b72if Te6edf3recorded_frames Tff7b72> Te6edf3required_framesTb4b4b4:
Te6edf3to_split Tff7b72= Tff7b72-Tffa657intTb4b4b4(Te6edf3recorded_framesTff7b72-Te6edf3required_framesTb4b4b4)
Te6edf3recorded_dataTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4, Tff7b72selfTff7b72.Td2a8ff_pending_chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffsplitTb4b4b4(Te6edf3recorded_dataTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4, Tb4b4b4[Te6edf3to_splitTb4b4b4]Tb4b4b4)
Te6edf3data Tff7b72= Te6edf3numpyTff7b72.Td2a8ffreshapeTb4b4b4(Te6edf3numpyTff7b72.Td2a8ffconcatenateTb4b4b4(Te6edf3recorded_dataTb4b4b4)Tb4b4b4, Tb4b4b4[Tff7b72-T79c0ff1Tb4b4b4, Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4]Tb4b4b4)
Tff7b72return Te6edf3dataTb4b4b4[Tb4b4b4:Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4]
Tff7b72def Td2a8ffflushTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return the last pending chunk
After using the record method, this will return the last incomplete
chunk and delete it.
"""
Te6edf3last_chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffreshapeTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_pending_chunkTb4b4b4, Tb4b4b4[Tff7b72-T79c0ff1Tb4b4b4, Tffa657lenTb4b4b4(Tffa657setTb4b4b4(Tff7b72selfTff7b72.Td2a8ffchannelmapTb4b4b4)Tb4b4b4)Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_pending_chunk Tff7b72= Te6edf3numpyTff7b72.Td2a8ffzerosTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3dtypeTff7b72=Ta5d6ff'Ta5d6fffloat32Ta5d6ff'Tb4b4b4)
Tff7b72return Te6edf3last_chunk
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────